package com.thread.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;

@Service
public class UseThreadPoolService {
    @Autowired
    private TaskExecutor asyncThreadPool;
    @Autowired
    private UsePoolBusinessService businessService;

    @Async
    public void executeService(int capacity) {
        Queue<FutureTask<String>> execute = execute(capacity);
        List<String> list = Collections.synchronizedList(new ArrayList<>());

        while (true) {
            FutureTask<String> poll = execute.poll();
            if (poll == null) {
                break;
            }
            try {
                String s = poll.get(3, TimeUnit.SECONDS);
                list.add(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                execute.add(poll);
                e.printStackTrace();
            }
        }
        System.out.println(list);
    }

    public Queue<FutureTask<String>> execute(int capacity) {
        Queue<FutureTask<String>> queue = new LinkedBlockingQueue<>(capacity);
        for (int i = 0; i < capacity; i++) {
            int index = i;
            FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return businessService.executeBusiness(index);
                }
            });
            queue.add(futureTask);
            asyncThreadPool.execute(futureTask);
        }

        return queue;
    }
}
